// 样式-数据-可拖拉拽树
import React from 'react';
import { connect } from 'react-redux';
import { Select, Tree, Input, Tooltip, Popconfirm } from 'antd';
import { SearchOutlined, PartitionOutlined, PlusSquareOutlined, FormOutlined, DeleteOutlined }  from '@ant-design/icons';
import { getAllTable, getDataTree, saveDataTree } from 'src/services/AnalyseManage';
import { WD_TYPE, DL_TYPE, DECIMAL_TYPES, INT_TYPES } from '../EnumConfig';
import { Scrollbars } from 'react-custom-scrollbars';
// import { debounce } from 'src/libs/utils';
import styles from './index.module.scss';
import ModalAddTier from './ModalAddTier';
import _ from 'lodash';

const colorBlue = { color: '#167DDC' };
const colorGreen = { color: '#87BD25' };

const { Option } = Select;

interface IProps {
	setCurrentReault: any;
	pageId: string;
	config: any;
	currentType: string;
	onValueChange: ( values: any ) => void;
	selectDisabled?: boolean;
	isDataResource: string; // Y/N
	btnAuth: any;
}

class ModelDataTree extends React.Component<IProps> {
	state: any = {
		tables: [],
		tree: [],
		currentDragType: '',
		wdFolderId: '',
		dlFolderId: '',
		tableCode: '',
		filterTree: [],
		expandedKeys: [],
		keyWord: '',
		modalVisible: false,
		curNode: null, //添加层级时
		nodeData: null, //重命名时
	};

	timer = null;
	dataList = [];

	componentDidMount() {
		const tableCode = this.props.config.data.tableCode;
		this.setState( { tableCode: tableCode }, () => {
			this.initData();
		} );
	}

	initCurrentTableCode = () => {
		const tables = this.state.tables;
		if ( tables.length > 0 ) {
			let defaultValue = '';
			const tableCode = this.props.config.data.tableCode;
			if ( tableCode !== '' ) {
				// tableCode 如果存在
				this.initColumn( this.state.tableCode );
			}

			if ( !this.state.tableCode ) {
				// 如果不存在 则需要初始化为第一个 tableCode
				const { onValueChange } = this.props;
				defaultValue = tables && tables.length > 0 ? tables[0].code : '';
				this.setState( { tableCode: defaultValue } );
				onValueChange( { tableCode: defaultValue } );
			}
		}
	};

	onChange( tree ) {
		console.log( tree );
	}

	initData = async () => {
		let pageResponse = await getAllTable( { roleSign: '' } );
		if ( pageResponse.data && pageResponse.data.success ) {
			let tables = pageResponse.data.data;
			this.setState( { tables: tables }, () => {
				this.initCurrentTableCode();
			} );
		}
	};

	initColumn = async ( code: string ) => {
		if ( !code ) return;

		const { isDataResource } = this.props;

		const reqParams = {
			// pageId: pageId,
			isDataResource,
			modelId: code,
		};

		let response = await getDataTree( reqParams );

		let enumConfig = {
			WD: WD_TYPE,
			DL: DL_TYPE,
		};

		if ( response.data && response.data.success ) {
			let dates = response.data.data;
			let treeData = [];
			dates.forEach( ( item: any ) => {
				let child = this.buildChild( item, enumConfig[item.type] );
				treeData.push( child );
			} );

			this.setState( { tree: treeData, filterTree: treeData, wdFolderId: treeData[0].id, dlFolderId: treeData[1].id, wdModelId: treeData[0].modelId, } );
		}
	};

	buildChild = ( item: any, type: string ) => {
		let childs = [];
		// console.log( '--buildChild--', item );
		item.children && item.children.forEach( ( childrenItem: any ) => {
			let child = this.buildChild( childrenItem, type );
			childs.push( child );
		} );
		return {
			...item,
			key: item.id,
			title: item.desc ? item.desc : item.name,
			children: childs,
			modelType: type,
			// icon: <CarryOutOutlined />,
		};
	};

	onDragEnter = ( info ) => {
		// console.log( 'dragenter', info.node );
		this.setState( { 
			currentDragType: 'dropenter',
			expandedKeys: info.expandedKeys,
		} );
	};

	componentDidUpdate( prevProps ) {
		if ( prevProps.config.key !== this.props.config.key ) {
			// console.log( 'update key' );
			const tableCode = this.props.config.data.tableCode;
			this.setState( { tableCode: tableCode }, () => {
				this.initCurrentTableCode();
			} );
		}
		let tableCode = this.props.config.data.tableCode;
		if ( tableCode && prevProps.config.data.tableCode !== tableCode ) {
			if ( !tableCode ) {
				tableCode = this.state.tables && this.state.tables.length > 0 ? this.state.tables[0] : '';
			}
			this.setState( { tableCode: tableCode }, () => {
				this.initColumn( tableCode );
			} );
		}
	}

	onDrop = async ( info ) => {
		console.log( '---info---', info );
		// 标记一下当前拖动的类型
		this.setState( { currentDragType: 'drop' }, () => {
			return;
		} );

		const { type: nodeType, modelType } = info.dragNode.props;

		if ( nodeType === 'DL' || nodeType === 'WD' ) {
			console.log( '禁止拖动维度或者度量' );
			return;
		}

		const parentId = info.node.parentId;
		const childrenType = info.node.childrenType;

		if ( !info.dropToGap && ( info.node.folderId === this.state.wdFolderId || 
			info.node.folderId === this.state.dlFolderId ) /*childrenType !== 'FOLDER'*/ ) {
			console.log( '禁止拖入非层级文件夹' );
			return;
		}

		if ( info.node.children.length > 0 ) {
			console.log( '禁止一层有多条数据' );
			return;
		}

		const dropKey = info.node.props.eventKey;
		const dropType = info.node.modelType;
		const dragKey = info.dragNode.props.eventKey;
		const dropPos = info.node.props.pos.split( '-' );
		const dropPosition = info.dropPosition - Number( dropPos[dropPos.length - 1] );
		const isFirstNode = info.node.childrenType === 'FOLDER' && info.node.children.length === 0 ? true: false;
		let dragNodeParentId = info.node.id;

		if ( [ 'WD', 'DL' ].includes( info.node.type ) && info.node.parentId === '0' ) {
			dragNodeParentId = '0';
		}

		let dragModelType, folderId;
		if ( modelType === 'WD' || dropType === WD_TYPE ) {
			dragModelType = WD_TYPE;
			folderId = this.state.wdFolderId;
		}

		if ( modelType === 'DL' || dropType === DL_TYPE ) {
			dragModelType = DL_TYPE;
			folderId = this.state.dlFolderId;
		}
		if ( !info.dropToGap && parentId !== '0' && childrenType === 'FOLDER' ) {
			folderId = dragNodeParentId; // 拖入层级给id
		} else if ( !info.dropToGap && childrenType === 'FIELD' ) {
			folderId = info.node.folderId; // 拖入层级内的某个字段给foloderId
		}
		console.log( folderId, dragNodeParentId, parentId, isFirstNode );

		const loop = ( data, key, callback ) => {
			for ( let i = 0; i < data.length; i++ ) {
				if ( data[i].key === key ) {
					return callback( data[i], i, data );
				}
				if ( data[i].children ) {
					loop( data[i].children, key, callback );
				}
			}
		};
		const data = [ ...this.state.tree ];

		let dragObj;
		loop( data, dragKey, ( item, index, arr ) => {
			arr.splice( index, 1 );
			dragObj = item;
		} );

		const rebuildChild = ( item: any ) => {
			let childs = [];
			item.children.forEach( ( childrenItem: any ) => {
				let child = rebuildChild( childrenItem );
				childs.push( child );
			} );
			return {
				...item,
				modelType: dragModelType,
				folderId: folderId,
				children: childs,
			};
		};

		dragObj = rebuildChild( dragObj );
		console.log( '-- dragObj --', dragObj );

		if ( !info.dropToGap ) {
			console.log( 'drop1' );

			// Drop on the content
			loop( data, dropKey, ( item ) => {
				item.children = item.children || [];
				// where to insert 示例添加到尾部，可以是随意位置，层级下第一级parentId为0
				item.children.push( { ...dragObj, parentId: isFirstNode ? '0' : dragNodeParentId } );
			} );
		} else if (
			( info.node.props.children || [] ).length > 0 && // Has children
			info.node.props.expanded && // Is expanded
			dropPosition === 1 // On the bottom gap
		) {
			console.log( 'drop2' );

			loop( data, dropKey, ( item ) => {
				item.children = item.children || [];
				// where to insert 示例添加到头部，可以是随意位置
				item.children.unshift( { ...dragObj, parentId: isFirstNode ? '0' :dragNodeParentId } );
			} );
		} else {
			console.log( 'drop3' );
			let ar;
			let i;
			loop( data, dropKey, ( item, index, arr ) => {
				ar = arr;
				i = index;
			} );
			if ( dropPosition === -1 ) {
				ar.splice( i, 0, { ...dragObj, parentId: '0' } );
			} else {
				ar.splice( i + 1, 0, { ...dragObj, parentId: '0' } );
			}
		}
		if ( data.length !== 2 ) {
			return;
		}

		this.setState( { tree: data }, () => {
			this.dataList = [];
			let filterTree = this.loopTreeList( this.state.keyWord, this.state.tree );
			let expandedKeys = [ ...this.state.expandedKeys, dragObj.id ];
			this.setState( {
				filterTree,
				expandedKeys,
			} );
		} );

		let newData = JSON.parse( JSON.stringify( data ) );

		let treeData = [];

		newData.forEach( ( item: any ) => {
			let child = this.buildSaveChild( item );
			delete child.isDimention;
			delete child.isMensure;
			treeData.push( child );
		} );

		saveDataTree( treeData );
	};

	buildSaveChild = ( item: any ) => {
		let childs = [];
		item.children.forEach( ( childrenItem: any ) => {
			let child = this.buildSaveChild( childrenItem );
			childs.push( child );
		} );
		item.isDimention = item.modelType === WD_TYPE ? 'Y' : 'N';
		item.isMensure = item.modelType === DL_TYPE ? 'Y' : 'N';
		// let name = item.title;
		delete item.key;
		delete item.title;
		delete item.modelType;
		// console.log( '------', item );
		return { ...item, children: childs };
	};

	handleChange = ( value ) => {
		// this.initColumn( value );
		const { onValueChange } = this.props;
		onValueChange( { tableCode: value } );
		this.setState( { tableCode: value } );
	};

	onDragEnd = ( { event, node } ) => {
		event.persist();
		// console.log( 'dragend', this.state.currentDragType, node.type );
		const { setCurrentReault } = this.props;

		if ( this.state.currentDragType === 'drop' || node.type === 'DL' || node.type === 'WD' ) {
			setCurrentReault( null );
		} else {
			setCurrentReault( node );
		}
		this.setState( { currentDragType: null } );
	};

	onDragLeave = () => {
		// console.log( 'dragleave' );
	};

	onExpand = ( expandedKeys ) => {
		this.setState( {
			expandedKeys,
		} );
	};

	handleSearchChange = ( e ) => {
		let keyWord = e.target.value.toLowerCase();
		// console.log( '== keyWord ==', keyWord );
		if ( this.timer ) clearTimeout( this.timer );
		this.timer = setTimeout( () => {
			this.dataList = [];
			let filterTree = this.loopTreeList( keyWord, this.state.tree );
			let expandedKeys = this.dataList.map( o => o.id );
			// console.log( '=== filterTree1 ===', filterTree );
			this.setState( {
				keyWord,
				filterTree,
				expandedKeys,
			} );
		}, 500 );
	};

	loopTreeList = ( keyWord, data ) => {
		if ( !keyWord ) return data;
		let list = data.map( node => {
			if ( node.children && node.children.length ) {
				this.dataList.push( node );
				return {
					...node,
					children: this.loopTreeList( keyWord, node.children ),
				};
			} else {
				let str = `${node.name} ${node.desc}`.toLowerCase();
				if ( ~str.indexOf( keyWord ) ) {
					this.dataList.push( node );
					return node;
				} else {
					return null;
				}
			}
		} );

		list = list.filter( node => node !== null );
		
		return list;
	};

	/* loopTreeNode( data ) {
		return data.map( ( d ) => {
			if ( d.children && d.children.length ) {
				return (
					<TreeNode key={d.key} title={d.name}>
						{this.loopTreeNode( d.children )}
					</TreeNode>
				);
			} else {
				return <TreeNode  key={d.key} title={d.name}></TreeNode>;
			}
		} );
	} */

	openModal = ( e, nodeData ) => {
		e.stopPropagation();
		this.setState( {
			curNode: nodeData,
			modalVisible: true,
		} );
	};

	// 添加层级/重命名层级弹窗
	toggleModal = ( value: boolean ) => {
		this.setState( { modalVisible: value } );
		if ( !value ) {
			this.setState( {
				curNode: null,
				nodeData: null,
			} );
		}
	};

	// 添加层级
	addTier = ( value: any ) => {
		console.log( '===addTier===', this.state.curNode );
		// 重命名时
		if ( value.id ) {
			const treeData = JSON.parse( JSON.stringify( this.state.tree ) );
			const { id, parentId } = this.state.nodeData;
			const node = {
				...this.state.nodeData,
				title: value.title,
				name: value.title,
				// desc: value.title,
			};
			treeData.forEach( item => {
				if ( item.id === parentId ) {
					let idx = _.findIndex( item.children, { id: id } );
					item.children.splice( idx, 1, node );
				}
			} );
			let filterTree = this.loopTreeList( this.state.keyWord, treeData );
			this.setState( {
				tree: treeData,
				filterTree,
			} );
			return;
		}

		this.initColumn( this.state.tableCode );

		/* let nodeData = this.state.curNode;
		const { type, id, parentId, modelType } = nodeData;
		const newId = new Date().getTime();
		const title = value.title || '自定义文件夹';
		const treeData = JSON.parse( JSON.stringify( this.state.tree ) );
		let data = {
			id: newId,
			key: newId,
			folderId: id,
			type,
			parentId,
			modelType,
			dataType: 'customFolder',
			title,
			name: title,
			desc: title,
			aliasName: '',
			sortOrder: null,
			children: [],
		};
		treeData.forEach( item => {
			if ( item.id === id ) {
				item.children.unshift( data );
			}
		} );
		let filterTree = this.loopTreeList( this.state.keyWord, treeData );
		this.setState( {
			tree: treeData,
			filterTree,
		} ); */
	};

	// 重命名层级
	handleRename = ( e, nodeData ) => {
		e.stopPropagation();
		this.setState( {
			modalVisible: true,
			nodeData,
		} );
	};

	// 删除层级
	handleDel = ( nodeData ) => {
		// e.stopPropagation();
		const treeData = JSON.parse( JSON.stringify( this.state.tree ) );
		const { id, parentId, children } = nodeData;
		console.log( '--删除层级--', nodeData );
		treeData.forEach( item => {
			if ( item.id === parentId ) {
				let idx = _.findIndex( item.children, { id } );
				if ( children && children.length ) {
					let childs = children.map( ch => {
						ch.folderId = parentId;
						ch.parentId = '0';
						return ch;
					} );
					item.children.splice( idx, 1, ...childs );
				} else {
					item.children.splice( idx, 1 );
				}
			}
		} );
		let filterTree = this.loopTreeList( this.state.keyWord, treeData );
		this.setState( {
			tree: treeData,
			filterTree,
		} );

		let newData = JSON.parse( JSON.stringify( treeData ) );
		let newTree = newData.map( ( item: any ) => {
			let child = this.buildSaveChild( item );
			delete child.isDimention;
			delete child.isMensure;
			return child;
		} );
		saveDataTree( newTree );
	};

	titleRender = ( nodeData ) => {
		const btnAuth = this.props.btnAuth;
		// 如果是根目录
		if ( !nodeData.dataType && nodeData.parentId === '0' && nodeData.type === 'WD' ) {
			return (
				<>
					<span>{ nodeData.title }</span>
					{
						btnAuth.includes( 'bi_dataSet_addTier' ) && (
							<span className={styles.add_tier} onClick={( e ) => this.openModal( e, nodeData )}>
								<PlusSquareOutlined /> 添加层级
							</span>
						)
					}
				</>
			);
		} else if ( nodeData.parentId !== '0' && nodeData.childrenType === 'FOLDER' ) {
			return (
				<>
					<span>{ nodeData.title }</span>
					{
						btnAuth.includes( 'bi_dataSet_addTier' ) && (
							<span className={ styles.btnwp }>
								<Tooltip placement="top" title="重命名层级">
									<FormOutlined className={ styles.greenBtn } 
										onClick={ ( e ) => this.handleRename( e, nodeData ) } />
								</Tooltip>
								<Tooltip placement="top" title="删除层级">
									<Popconfirm
										okText="确定" cancelText="取消" title="确定删除这一项？" placement="bottom"
										onConfirm={ () => this.handleDel( nodeData ) }>
										<DeleteOutlined className={ styles.greenBtn }
											onClick={ ( e ) => { e.stopPropagation(); } } />
									</Popconfirm>
								</Tooltip>
							</span>
						)
					}
				</>
			);
		}
		return (
			<>{ nodeData.title }</>
		);
	};

	render() {
		let tables = this.state.tables;
		const children = [];
		tables.forEach( ( v, key ) => {
			children.push(
				<Option style={{ width: '100%' }} value={v.code} key={v.code}>
					{v.toTableDesc}
				</Option>
			);
		} );

		return (
			<div style={{ height: '100%' }}>
				<div style={{ width: '100%', height: 40 }}>
					<Select disabled={ !!this.props.selectDisabled } style={{ width: '100%' }} onChange={this.handleChange} value={this.state.tableCode}>
						{children}
					</Select>
				</div>

				<div style={{ width: '100%', height: 40 }}>
					<Input placeholder="请输入" 
						allowClear 
						onChange={ this.handleSearchChange }
						prefix={<SearchOutlined />} />
				</div>

				<Scrollbars style={{ height: 'calc(100% - 80px)' }}
					autoHide
					autoHideTimeout={1000}
					autoHideDuration={300}
				>
					<Tree
						className="draggable-tree"
						titleRender={this.titleRender}
						onDragEnter={this.onDragEnter}
						onDrop={this.onDrop}
						onDragLeave={this.onDragLeave}
						onExpand={ this.onExpand }
						expandedKeys={this.state.expandedKeys}
						treeData={this.state.filterTree}
						onDragEnd={this.onDragEnd}
						icon={( props: any ) => {
							const { dataType, childrenType, parentId } = props;
							if ( !dataType && parentId === '0' ) {
								// 如果是根目录PartitionOutlined
								return <span className={'iconfont bdhwenjianjiaguanbi'}></span>;
							} else if( parentId !== '0' && childrenType === 'FOLDER' ) {
								// 自定义层级
								return <PartitionOutlined />;
							} else if( [ 'TIME' ].indexOf( dataType.toUpperCase() ) !== -1 ) {
								// 时间
								return <span className={'iconfont bdhshijianriqi'} style={ colorBlue }></span>;
							} else if( [ 'DATE', 'DATETIME', 'TIMESTAMP' ].indexOf( dataType.toUpperCase() ) !== -1 ) {
								// 日期
								return <span className={'iconfont bdhshijianriqi'} style={ colorBlue }></span>;
							} else if( INT_TYPES.indexOf( dataType.toUpperCase() ) !== -1 ) {
								// 整数
								return <span className={'iconfont bdhzhengshu'} style={ colorGreen }></span>;
							} else if( DECIMAL_TYPES.indexOf( dataType.toUpperCase() ) !== -1 ) {
								// 小数
								return <span className={'iconfont bdhzhengshubeifen'} style={ colorBlue }></span>;
							} else {
								// 字符串文本
								return <span className={'iconfont bdhwenben'} style={ colorGreen }></span>;
							}
						}}
						showIcon
						draggable
						blockNode
					></Tree>
				</Scrollbars>

				<ModalAddTier
					modalVisible={this.state.modalVisible}
					nodeData={this.state.nodeData}
					folderId={this.state.wdFolderId}
					modelId={this.state.wdModelId}
					type={'WD'}
					onSubmit={this.addTier}
					closeModal={this.toggleModal}
				/>
			</div>
		);
	}
}

//	映射state到当前组件
const mapStateToProps = ( state ) => {
	return {
		btnAuth: state.btnAuth,
	};
};

export default connect( mapStateToProps )( ModelDataTree );
